package com.gzhryc.net_marketing.cloud.account.services;

import com.gzhryc.common.IDTools;
import com.gzhryc.common.NumberTools;
import com.gzhryc.common.event.DelayHandleService;
import com.gzhryc.common.exceptions.LogicException;
import com.gzhryc.common.logging.Logger;
import com.gzhryc.jdbc.Conditions;
import com.gzhryc.jdbc.JdbcSession;
import com.gzhryc.jdbc.MultiDBTools;
import com.gzhryc.jdbc.utils.JsonTools;
import com.gzhryc.net_marketing.cloud.MarketConstants;
import com.gzhryc.net_marketing.cloud.account.dao.CloudPayAccountWithdrawOrderDao;
import com.gzhryc.net_marketing.cloud.account.dao.db.CloudPayAccount;
import com.gzhryc.net_marketing.cloud.account.dao.db.CloudPayAccountWithdrawOrder;
import com.gzhryc.net_marketing.cloud.account.dao.db.CloudPayAccountWithdrawPayee;
import com.gzhryc.net_marketing.cloud.account.dao.db.TransferMoneyOrder;
import com.gzhryc.net_marketing.cloud.account.dao.enums.CloudPayAccountOperateRecordEnum;
import com.gzhryc.net_marketing.cloud.account.dao.enums.CloudPayAccountWithdrawOrderEnum;
import com.gzhryc.net_marketing.cloud.account.delay.TransferMoneyDelayEvent;
import com.gzhryc.net_marketing.cloud.account.services.dto.CloudPayAccountWithdrawOrderSearch;
import com.gzhryc.pay.adaptation.weixin.msg.WXReceivingInfo;
import com.gzhryc.pay.enums.ReceivingMoneyType;
import com.gzhryc.shared_device.base.enums.EPayType;
import com.gzhryc.system.dao.db.Manager;

import java.sql.SQLException;
import java.util.Date;
import java.util.List;

public class CloudPayAccountWithdrawOrderService {

    static Logger log = Logger.getLogger(CloudPayAccountWithdrawOrderService.class);

    public static CloudPayAccountWithdrawOrderService self() {
        return MultiDBTools.getService(MarketConstants.JDBC_KEY,CloudPayAccountWithdrawOrderService.class, true);
    }

    CloudPayAccountWithdrawOrderDao dao;

    public CloudPayAccountWithdrawOrderService(String jdbcKey) {
        this.dao = new CloudPayAccountWithdrawOrderDao(jdbcKey);
    }

    public List<CloudPayAccountWithdrawOrder> findBySearch(CloudPayAccountWithdrawOrderSearch search, Integer pageNo, Integer pageLimit){
        Conditions conditions = dao.buildConditions(search);
        conditions.desc("createDate");
        try {
            return dao.findByCondition(conditions,pageNo,pageLimit);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return null;
    }

    public Long countBySearch(CloudPayAccountWithdrawOrderSearch search){
        Conditions conditions = dao.buildConditions(search);
        try {
            return dao.count(conditions);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return 0L;
    }

    public CloudPayAccountWithdrawOrder getByTradeNo(String tradeNo){
        try {
            return dao.getById(tradeNo);
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        }
        return null;
    }

    public CloudPayAccountWithdrawOrder add(CloudPayAccount account, CloudPayAccountWithdrawPayee withdrawUser, Integer money) throws LogicException {
        if(account.getMoney() < money){
            throw new LogicException("账号余额不足");
        }

        //冻结金额
        if(CloudPayAccountService.self().reduceMoney(account,money,withdrawUser.getName(),
                "用户取款" + NumberTools.getMoneyStr(money) + "元")) {
            CloudPayAccountWithdrawOrder withdrawOrder = new CloudPayAccountWithdrawOrder();
            withdrawOrder.setTradeNo(account.getId() + IDTools.getTimestampSecondID());
            withdrawOrder.setTitle("用户取款" + NumberTools.getMoneyStr(money) + "元");
            withdrawOrder.setAccountId(account.getId());
            withdrawOrder.setPayType(EPayType.WXPay.index());
            withdrawOrder.setAppId(account.getWxpayAppId());
            withdrawOrder.setHandleType(CloudPayAccountWithdrawOrderEnum.HandleType.AutoTransfer.index());

            withdrawOrder.setReceivingId(withdrawUser.getOpenId());
            withdrawOrder.setReceivingFaceImg(withdrawUser.getFaceImg());
            withdrawOrder.setReceivingNickname(withdrawUser.getNickname());
            withdrawOrder.setReceivingName(withdrawUser.getName());
            withdrawOrder.setReceivingPhone(withdrawUser.getPhone());

            withdrawOrder.setMoney(money);
            withdrawOrder.setPayMoney(money);

            withdrawOrder.setState(CloudPayAccountWithdrawOrderEnum.State.WaitVerify.index());
            withdrawOrder.setCreateDate(new Date());
            try {
                if (dao.insert(withdrawOrder) > 0) {
                    return withdrawOrder;
                }
            } catch (SQLException e) {
                log.error(e.getMessage(), e);
            }
        }
        return null;
    }

    public boolean reject(String tradeNo, String rejectReason, Manager manager) throws LogicException {
        CloudPayAccountWithdrawOrder withdrawOrder = getByTradeNo(tradeNo);
        if(withdrawOrder == null){
            throw new LogicException("未找到取款订单信息");
        }

        if(!CloudPayAccountWithdrawOrderEnum.State.WaitVerify.index().equals(withdrawOrder.getState())){
            throw new LogicException("取款订单信息已处理");
        }

        CloudPayAccount account = CloudPayAccountService.self().getById(withdrawOrder.getAccountId());
        if(account == null){
            throw new LogicException("未找到云支付账号");
        }

        if(account.getFreezeMoney() < withdrawOrder.getMoney()){
            throw new LogicException("云支付账号冻结金额不足");
        }

        Conditions conditions = new Conditions(CloudPayAccountWithdrawOrder.class);
        conditions.and().is("tradeNo",tradeNo);
        conditions.and().is("state",CloudPayAccountWithdrawOrderEnum.State.WaitVerify.index());

        CloudPayAccountWithdrawOrder updateEntity = new CloudPayAccountWithdrawOrder();
        updateEntity.setHandleType(CloudPayAccountWithdrawOrderEnum.HandleType.ManualTransfer.index());
        updateEntity.setState(CloudPayAccountWithdrawOrderEnum.State.Reject.index());
        updateEntity.setRejectReason(rejectReason);
        updateEntity.setOperator(CloudPayAccountWithdrawOrderEnum.OperatorType.Manager.note());
        updateEntity.setOperator(manager.getFullName());
        updateEntity.setOperateDate(new Date());

        JdbcSession.begin();
        try {
            if(dao.updateNotNull(updateEntity,conditions) > 0) {
                //解冻金额
                if (CloudPayAccountService.self().unfreezeMoney(account, withdrawOrder.getMoney(),
                        CloudPayAccountOperateRecordEnum.OperatorType.Manager.index(), manager.getFullName(), "驳回" + withdrawOrder.getTradeNo() + "取款订单")) {
                    JdbcSession.commit();
                    return true;
                }
            }
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        } finally {
            JdbcSession.end();
        }
        return false;
    }

    public boolean manualProcessing(String tradeNo, Integer transferType,String transferAccount,String transferTradeNo, Manager manager) throws LogicException {
        CloudPayAccountWithdrawOrder withdrawOrder = getByTradeNo(tradeNo);
        if(withdrawOrder == null){
            throw new LogicException("未找到取款订单信息");
        }

        if(!CloudPayAccountWithdrawOrderEnum.State.WaitVerify.index().equals(withdrawOrder.getState())){
            throw new LogicException("取款订单信息已处理");
        }

        CloudPayAccount account = CloudPayAccountService.self().getById(withdrawOrder.getAccountId());
        if(account == null){
            throw new LogicException("未找到云支付账号");
        }

        if(account.getFreezeMoney() < withdrawOrder.getMoney()){
            throw new LogicException("云支付账号冻结金额不足");
        }

        Conditions conditions = new Conditions(CloudPayAccountWithdrawOrder.class);
        conditions.and().is("tradeNo",tradeNo);
        conditions.and().is("state",CloudPayAccountWithdrawOrderEnum.State.WaitVerify.index());

        CloudPayAccountWithdrawOrder updateEntity = new CloudPayAccountWithdrawOrder();
        updateEntity.setHandleType(CloudPayAccountWithdrawOrderEnum.HandleType.ManualTransfer.index());
        updateEntity.setState(CloudPayAccountWithdrawOrderEnum.State.Success.index());
        updateEntity.setTransferType(transferType);
        updateEntity.setTransferAccount(transferAccount);
        updateEntity.setTransferTradeNo(transferTradeNo);
        updateEntity.setOperator(CloudPayAccountWithdrawOrderEnum.OperatorType.Manager.note());
        updateEntity.setOperator(manager.getFullName());
        updateEntity.setOperateDate(new Date());

        JdbcSession.begin();
        try {
            if(dao.updateNotNull(updateEntity,conditions) > 0) {
                //解冻金额
                if (CloudPayAccountService.self().reduceFreezeMoney(account, withdrawOrder.getMoney(),
                        CloudPayAccountOperateRecordEnum.OperatorType.Manager.index(), manager.getFullName(), "人工处理" + withdrawOrder.getTradeNo() + "取款订单完成")) {
                    JdbcSession.commit();
                    return true;
                }
            }
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        } finally {
            JdbcSession.end();
        }
        return false;
    }

    public boolean autoProcessing(String tradeNo, Manager manager) throws LogicException {
        CloudPayAccountWithdrawOrder withdrawOrder = getByTradeNo(tradeNo);
        if(withdrawOrder == null){
            throw new LogicException("未找到取款订单信息");
        }

        if(!CloudPayAccountWithdrawOrderEnum.State.WaitVerify.index().equals(withdrawOrder.getState())){
            throw new LogicException("取款订单信息已处理");
        }

        CloudPayAccount account = CloudPayAccountService.self().getById(withdrawOrder.getAccountId());
        if(account == null){
            throw new LogicException("未找到云支付账号");
        }

        if(account.getFreezeMoney() < withdrawOrder.getMoney()){
            throw new LogicException("云支付账号冻结金额不足");
        }

        Conditions conditions = new Conditions(CloudPayAccountWithdrawOrder.class);
        conditions.and().is("tradeNo",tradeNo);
        conditions.and().is("state",CloudPayAccountWithdrawOrderEnum.State.WaitVerify.index());

        CloudPayAccountWithdrawOrder updateEntity = new CloudPayAccountWithdrawOrder();
        updateEntity.setHandleType(CloudPayAccountWithdrawOrderEnum.HandleType.AutoTransfer.index());
        updateEntity.setState(CloudPayAccountWithdrawOrderEnum.State.Processing.index());
        updateEntity.setOperator(CloudPayAccountWithdrawOrderEnum.OperatorType.Manager.note());
        updateEntity.setOperator(manager.getFullName());
        updateEntity.setOperateDate(new Date());

        boolean flag = false;
        TransferMoneyOrder order = null;
        JdbcSession.begin();
        try {
            if(dao.updateNotNull(updateEntity,conditions) > 0) {
                order = new TransferMoneyOrder();
                order.setTradeNo(withdrawOrder.getTradeNo());
                order.setAccountId(withdrawOrder.getAccountId());
                order.setPayType(EPayType.WXPay.index());
                order.setAppId(withdrawOrder.getAppId());
                order.setMoney(withdrawOrder.getPayMoney());//实际转账金额

                order.setReceivingType(ReceivingMoneyType.Account.index());

                WXReceivingInfo receivingInfo = new WXReceivingInfo();
                receivingInfo.setAppId(withdrawOrder.getAppId());
                receivingInfo.setNickname(withdrawOrder.getReceivingName());
                receivingInfo.setOpenid(withdrawOrder.getReceivingId());
                order.setReceivingInfo(JsonTools.toJson(receivingInfo));

                if(TransferMoneyOrderService.self().add(order)) {
                    //解冻金额
                    if (CloudPayAccountService.self().reduceFreezeMoney(account, withdrawOrder.getMoney(),
                            CloudPayAccountOperateRecordEnum.OperatorType.Manager.index(), manager.getFullName(), "自动处理" + withdrawOrder.getTradeNo() + "取款订单完成")) {

                        JdbcSession.commit();
                        flag = true;
                    }
                }
            }
        } catch (SQLException e) {
            log.error(e.getMessage(),e);
        } finally {
            JdbcSession.end();
        }

        if(flag){
            TransferMoneyDelayEvent event = new TransferMoneyDelayEvent(order);
            DelayHandleService.get().addEvent(event);
        }
        return false;
    }

}
